<?php

namespace addons\yunfood\library;

use addons\epay\library\Service;
use addons\yunfood\model\Payment;
use addons\yunfood\model\Refundment;
use addons\yunfood\model\UserAuth;
use think\Exception;
use think\Log;
use think\Request;
use Yansongda\Pay\Pay;

class PayService
{
    /**
     * 提交支付请求
     *
     * @param $paymentData
     * @return \Yansongda\Supports\Collection
     */
    public static function submitPayment(Payment $paymentData)
    {
        list($type, $method) = explode('-', $paymentData->channel);
        $params = [
            'type'      => $type,  // wechat、alipay
            'orderid'   => $paymentData->trade_no,
            'title'     => $paymentData->goods_name,
            'amount'    => $paymentData->goods_amount,
            'method'    => $method, // web、wap、app、scan、pos、mp，miniapp
            'auth_code' => null,
            // 必须配置，不然会被重置
            'notifyurl' => (Request::instance())->domain() . '/index.php/addons/yunfood/web/payCallback/type/' . $type,
            'returnurl' => '',
        ];
        if (in_array($method, ['mp', 'miniapp'])) {
            $source = null;
            if ($method === 'mp') {
                $source = UserAuth::SOURCE_MP;
            } elseif ($method === 'miniapp') {
                $source = UserAuth::SOURCE_MINI;
            }
            if (! $userAuth = UserAuth::get(['user_id' => $paymentData->user_id, 'source' => $source])) {
                throw new Exception('获取微信用户信息失败');
            }
            $params['openid'] = $userAuth->openid;
        }
        Log::write('payment before ' . 'type=' . $type . ', params=' . json_encode($params));
        $result = Service::submitOrder($params);
        Log::write('payment after payment_trade_no=' . $paymentData->trade_no . ', result=' . json_encode($result));

        return $result;
    }

    /**
     * @param $type
     */
    public static function notifyPayment($type, $callback)
    {
        $pay = self::getPay($type, 'pay');
        try {
            $data = $pay->verify();
            Log::write('支付回调数据 data=' . json_encode($data));

            // 微信支付通知
            // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
            // 支付宝支付通知
            // https://opendocs.alipay.com/support/01rawc?pathHash=4ad70fe3

            // 微信支付成功回调参数
//            {
//                "bank_type": "OTHERS",
//                "cash_fee": "1",
//                "fee_type": "CNY",
//                "is_subscribe": "N",
//                "mch_id": "1648792358",
//                "nonce_str": "ib8SZfXReB27hskX",
//                "openid": "oW5Vn5DpppNKxN3uckH-T_mW-YQY",
//                "out_trade_no": "20241021558518",
//                "result_code": "SUCCESS",
//                "return_code": "SUCCESS",
//                "sign": "D6FD7E873A01B16FFE4D6B6912616390",
//                "time_end": "20241021233527",
//                "total_fee": "1",
//                "trade_type": "JSAPI",
//                "transaction_id": "4200002328202410214721521109"
//            }

            // 支付宝支付成功回调参数
            // {
            //     "gmt_create":"2020-04-10 19:15:00",
            //     "charset":"utf-8",
            //     "seller_email":"xptech@qq.com",
            //     "subject":"\u5546\u57ce\u8ba2\u5355\u652f\u4ed8",
            //     "sign":"AOiYZ1a2mEMOuIbHFCi6V6A0LJ97UMiHsCWgNdSU9dlzKFl15Ts8b0mL\/tN+Hhskl+94S3OUiNTBD3dD0Kv923SqaTWxNdj533PCdo2GDKsZIZgKbavnOvaccSKUdmQRE9KtmePPq9V9lFzEQvdUkKq1M8KAWO5K9LTy2iT2y5CUynpiu\/04GVzsTL9PqY+LDwqj6K+w7MgceWm1BWaFWg27AXIRw7wvsFckr3k9GGajgE2fufhoCYGYtGFbhGOp6ExtqS5RXBuPODOyRhBLpD8mwpOX38Oy0X+R4YQIrOi02dhqwPpvw79YjnvgXY3qZEQ66EdUsrT7EBdcPHK0Gw==",
            //     "buyer_id":"2088902485164146",
            //     "invoice_amount":"0.01",
            //     "notify_id":"2020041000222191501064141414240102",
            //     "fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"PCREDIT\"}]",
            //     "notify_type":"trade_status_sync",
            //     "trade_status":"TRADE_SUCCESS",
            //     "receipt_amount":"0.01",
            //     "buyer_pay_amount":"0.01",
            //     "sign_type":"RSA2",
            //     "seller_id":"2088721922277739",
            //     "gmt_payment":"2020-04-10 19:15:00",
            //     "notify_time":"2020-04-10 19:15:01",
            //     "version":"1.0",
            //     "out_trade_no":"202007144778322770017000",
            //     "total_amount":"0.01",
            //     "trade_no":"2020041022001464141443020240",
            //     "auth_app_id":"2021001114666742",
            //     "buyer_logon_id":"157***@163.com",
            //     "point_amount":"0.00"
            // }
        } catch (\Exception $e) {
            Log::write('支付验证错误', $e->getMessage());
            return 'fail';
        }

        // 微信支付
        if ($type === 'wechat') {
            $paymentTradeNo = $data['out_trade_no'];
            $paymentAmount = $data['total_fee'] / 100;
            // result_code 通信code
            // return_code 业务code
            $paymentStatus = $data['result_code'] === 'SUCCESS' && $data['return_code'] === 'SUCCESS' ? true : false;
        } else {
            // 支付宝支付
            $paymentTradeNo = $data['out_trade_no'];
            $paymentAmount = $data['total_amount'];
            // TRADE_SUCCESS - 交易成功 - 支持退款
            // TRADE_FINISHED - 交易完成 - 不支持退款
            $paymentStatus = in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED']) ? true : false;
        }
        $result = compact('paymentTradeNo', 'paymentAmount', 'paymentStatus');

        return $callback($result, $pay);
    }

    /**
     * 提交退款请求
     *
     * @param $refundmentData
     */
    public static function submitRefundment(Refundment $refundmentData)
    {
        list($type, $method) = explode('-', $refundmentData->channel);

        $pay = self::getPay($type, 'refund');
        $params = [
            'out_trade_no' => $refundmentData->out_trade_no,
        ];

        // 微信支付
        if ($type === 'wechat') {
            $params = array_merge($params, [
                'out_refund_no' => $refundmentData->trade_no,
                'total_fee'     => $refundmentData->payment_amount * 100,
                'refund_fee'    => $refundmentData->refund_amount * 100,
                'refund_desc'   => $refundmentData->refund_remark
            ]);
        } else {
            // 支付宝支付
            $params = array_merge($params, [
                'out_request_no' => $refundmentData->trade_no,
                'refund_amount'  => $refundmentData->refund_amount,
                'refund_reason'  => $refundmentData->refund_remark
            ]);
        }
        if ($type === 'wechat' && $method === 'miniapp') {
            $params['type'] = 'miniapp';
        }
        Log::write('refund before ' . 'type=' . $type . ', params=' . json_encode($params));
        $result = $pay->refund($params);
        Log::write('refund after refund_trade_no=' . $refundmentData->trade_no . ', result=' . json_encode($result));

        // 微信返回结果
//        {
//            "return_code": "SUCCESS",
//            "return_msg": "OK",
//            "mch_id": "1648792358",
//            "nonce_str": "fbRY7mX0FJvzvU6l",
//            "sign": "68B8179115B9B126FB1317CDD66F6835",
//            "result_code": "SUCCESS",
//            "transaction_id": "4200002327202410228018991675",
//            "out_trade_no": "20241022579174",
//            "out_refund_no": "20241022587319",
//            "refund_id": "50303501272024102235759302042",
//            "refund_channel": [],
//            "refund_fee": "1",
//            "coupon_refund_fee": "0",
//            "total_fee": "1",
//            "cash_fee": "1",
//            "coupon_refund_count": "0",
//            "cash_refund_fee": "1"
//        }

        // 支付宝返回结果
        // {
        //     "code": "10000",
        //     "msg": "Success",
        //     "buyer_logon_id": "157***@163.com",
        //     "buyer_user_id": "2088902485164146",
        //     "fund_change": "Y",
        //     "gmt_refund_pay": "2020-08-15 16:11:45",
        //     "out_trade_no": "202002460317545607015300",
        //     "refund_fee": "0.01",
        //     "send_back_fee": "0.00",
        //     "trade_no": "2020081522001464141438570535"
        // }

        // 请求结果
        if ($type == 'wechat') {
            // return_code 通信code
            // result_code 业务code
            if ($result['return_code'] !== 'SUCCESS' || $result['result_code'] !== 'SUCCESS') {
                throw new \Exception($result['return_msg']);
            }
        } else {
            if ($result['code'] != 10000) {
                throw new \Exception($result['msg']);
            }
        }

        return true;
    }

    /**
     * @param $type
     */
    public static function notifyRefundment($type, $callback)
    {
        $pay = self::getPay($type, 'refund');
        try {
            $data = $pay->verify(null, true);
            Log::write('退款回调数据 data=' . json_encode($data));
            // 微信退款通知
            // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10
            // 支付宝退款通知
            // https://opendocs.alipay.com/support/01rawc?pathHash=4ad70fe3

            // 微信退款成功的回调参数
//            {
//                "cash_refund_fee": "1",
//                "out_refund_no": "20241022577131",
//                "out_trade_no": "20241021565081",
//                "refund_account": "REFUND_SOURCE_RECHARGE_FUNDS",
//                "refund_fee": "1",
//                "refund_id": "50302501182024102234405180236",
//                "refund_recv_accout": "支付用户零钱通",
//                "refund_request_source": "API",
//                "refund_status": "SUCCESS",
//                "settlement_refund_fee": "1",
//                "settlement_total_fee": "1",
//                "success_time": "2024-10-22 00:02:06",
//                "total_fee": "1",
//                "transaction_id": "4200002348202410219086761505",
//                "return_code": "SUCCESS",
//                "mch_id": "1648792358",
//                "nonce_str": "a4d6712b1493e97fc1842b5e52cd5de1"
//            }

            // 支付宝退款成功（交易关闭）的回调参数
            // {
            //     "gmt_create": "2020-08-15 14:48:32",
            //     "charset": "utf-8",
            //     "seller_email": "xptech@qq.com",
            //     "gmt_payment": "2020-08-15 14:48:32",
            //     "notify_time": "2020-08-15 16:11:45",
            //     "subject": "商城订单支付",
            //     "gmt_refund": "2020-08-15 16:11:45.140",
            //     "sign": "b6ArkgzLIRteRL9FMGC6i\/jf6VwFYQbaGDGRx002W+pdmN5q9+O4edZ3ALF74fYaijSl9ksNr0dKdvanu3uYxBTcd\/GIS4N1CWzmCOv6pzgx5rO\/YvGoHLM3Yop0GKKuMxmnNsZ6jhYKEY7SYD3Y0L6PU9ZMdHV7yIiVj+zZmbKzUgK9MPDCEXs+nzpNAiSM8GTqYRSUvKobAK68hswG2k1QIcqr5z+ZmVYa\/nHHkoC9qXt5zwyGi4P+2eOsr6V2PjA3x8qqe7TN5aI1DeoZD5KqHPYYaYF17J2q6YPlgl3WUl1RhE7H86bivB1fIuYEv\/3+JR74WN\/o7krGw1RPHg==",
            //     "out_biz_no": "R202004114414846255015300",
            //     "buyer_id": "2088902485164146",
            //     "version": "1.0",
            //     "notify_id": "2020081500222161145064141453349793",
            //     "notify_type": "trade_status_sync",
            //     "out_trade_no": "202002460317545607015300",
            //     "total_amount": "0.01",
            //     "trade_status": "TRADE_CLOSED",
            //     "refund_fee": "0.01",
            //     "trade_no": "2020081522001464141438570535",
            //     "auth_app_id": "2021001114666742",
            //     "buyer_logon_id": "157***@163.com",
            //     "gmt_close": "2020-08-15 16:11:45",
            //     "sign_type": "RSA2",
            //     "seller_id": "2088721922277739"
            // }
        } catch (\Exception $e) {
            Log::write('退款验证错误', $e->getMessage());
            return 'fail';
        }

        // 微信退款
        if ($type === 'wechat') {
            $refundmentTradeNo = $data['out_refund_no'];
            $refundmentAmount = $data['total_fee'] / 100;
            // return_code 通信code
            // refund_status 退款结果
            $refundmentStatus = $data['return_code'] === 'SUCCESS' && $data['refund_status'] === 'SUCCESS' ? true : false;
        } else {
            // 支付宝退款
            $refundmentTradeNo = $data['out_biz_no'];
            $refundmentAmount = $data['refund_fee'];
            // TRADE_SUCCESS - 部分退款
            // TRADE_CLOSED - 全额退款
            $refundmentStatus = in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_CLOSED']) ? true : false;
        }
        $result = compact('refundmentTradeNo', 'refundmentAmount', 'refundmentStatus');

        return $callback($result, $pay);
    }

    public static function getPay($type, $scene)
    {
        $config = self::getConfig($type, $scene);
        switch ($type) {
            case 'wechat':
                $pay = Pay::wechat($config);
                break;
            case 'alipay':
                $pay = Pay::alipay($config);
                break;
            default:
                throw new Exception('不支持的支付方式');
        }
        return $pay;
    }

    private static function getConfig($type, $scene)
    {
        $config = Service::getConfig($type);
        $config['notify_url'] = (Request::instance())->domain()
            . '/index.php/addons/yunfood/web/' . $scene . 'Callback/type/' . $type;

        return $config;
    }
}

